﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Text.RegularExpressions;

namespace KrisThom
{
    
    public class VirusTotalResults
    {

        public enum Status { Error = -1, Unknown = 0, Success = 1, InternalError = 99 }
        public enum ResultType { Scan, Report, Unknown }

        public ResultType Type { get; set; }
        public DateTime ReportDate;
        public Status ResultStatus { get; set; }
        public string PermaLink { get; set; }
        public Dictionary<String, String> AntiVirus { get; set; }
        public int MalwarePercent { get; set; }
        public String JSON { get; set; }
        public Boolean MalwareFound { get; set; }
        public String InternalErrorMessage { get; set; }
                  
        public VirusTotalResults()
        {
        }

        public VirusTotalResults(String json)
        {
            try
            {
                //{"report": ["2010-10-25 22:52:19", {"nProtect": "EICAR-Test-File", "CAT-QuickHeal": "EICAR Test File", "McAfee": "EICAR test file", "K7AntiVirus": "EICAR_Test_File", "TheHacker": "EICAR_Test_File", "VirusBuster": "EICAR_test_file", "NOD32": "Eicar test file", "F-Prot": "EICAR_Test_File", "Symantec": "EICAR Test String", "Norman": "EICAR_Test_file_not_a_virus!", "TrendMicro-HouseCall": "Eicar_test_file", "Avast": "EICAR Test-NOT virus!!!", "eSafe": "EICAR Test File", "ClamAV": "Eicar-Test-Signature", "Kaspersky": "EICAR-Test-File", "BitDefender": "EICAR-Test-File (not a virus)", "ViRobot": "EICAR-test", "Emsisoft": "EICAR-ANTIVIRUS-TESTFILE!IK", "Comodo": "Teststring.Eicar", "F-Secure": "EICAR_Test_File", "DrWeb": "EICAR Test File (NOT a Virus!)", "AntiVir": "Eicar-Test-Signature", "TrendMicro": "Eicar_test_file", "McAfee-GW-Edition": "EICAR test file", "Sophos": "EICAR-AV-Test", "eTrust-Vet": "the EICAR test string", "Authentium": "EICAR_Test_File", "Jiangmin": "EICAR-Test-File", "Antiy-AVL": "AVTEST/EICAR.ETF", "Microsoft": "Virus:DOS/EICAR_Test_File", "SUPERAntiSpyware": "NotAThreat.EICAR[TestFile]", "Prevx": "EICAR", "GData": "EICAR-Test-File", "AhnLab-V3": "EICAR_Test_File", "VBA32": "EICAR-Test-File", "Sunbelt": "EICAR (v)", "PCTools": "Virus.DOS.EICAR_test_file", "Rising": "EICAR-Test-File", "Ikarus": "EICAR-ANTIVIRUS-TESTFILE", "Fortinet": "EICAR_TEST_FILE", "AVG": "EICAR_Test", "Panda": "EICAR-AV-TEST-FILE", "Avast5": "EICAR Test-NOT virus!!!"}], "permalink": "http://www.virustotal.com/file-scan/report.html?id=275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f-1288047139", "result": 1}
                //{"scan_id": "cd1384c10baa2d5b96f397b986e2a1fc9535d2ef0e185a113fc610eca1c6fb0e-1271623480", "result": 1}
                
                JSON = json;
                Type = ParseResultsType(json);
                ResultStatus = ParseResultStatus(json, Type);

                switch (Type)
                {
                    case ResultType.Report:
                        ReportDate = ParseReportDate(json);
                        PermaLink = ParsePermaLink(json, Type);
                        AntiVirus = ParseAntiVirus(json);
                        MalwarePercent = ParseMalwarePercent(ParseMalwareCount(AntiVirus), AntiVirus.Count());
                        MalwareFound = ParseMalwareFound(AntiVirus.Count);
                        break;

                    case ResultType.Scan:
                        PermaLink = ParsePermaLink(json, Type);
                        break;
                }

            }
            catch (Exception ex)
            {
                ResultStatus = Status.InternalError;
                InternalErrorMessage = ex.Message;
            }
        }

        


        private ResultType ParseResultsType(String json)
        {
            try
            {
                if (json.StartsWith("{\"report\":"))
                {
                    return ResultType.Report;
                }
                else if (json.StartsWith("{\"scan_id\":"))
                {
                    return ResultType.Scan;
                }
                else
                {
                    return ResultType.Unknown;
                }
            }
            catch
            {
                throw;
            }
        }

        private Status ParseResultStatus(String json, ResultType type)
        {
            try
            {
                if (type == ResultType.Report)
                {
                    int value = (Convert.ToInt32(Regex.Split(json, "}],", RegexOptions.None)[1].Split(new char[] { ',' })[1].Split(new char[] { '}' })[0].Split(new char[] { ':' })[1].Replace("\"", "").Trim()));
                    return (Status)value;
                }
                else if (type == ResultType.Scan)
                {
                    int value = (Convert.ToInt32(json.Split(new char[] { ',' })[1].Split(new char[] { ':' })[1].Split(new char[] { '}' })[0].Replace("\"", "").Trim()));
                    return (Status)value;
                }
                else
                {
                    throw new NotImplementedException("Result type is unknown!");
                }
            }
            catch
            {
                throw;
            }
        }

        private String ParsePermaLink(String json, ResultType type)
        {
            try
            {
                if (type == ResultType.Report)
                {

                    return Regex.Split(json, "}],", RegexOptions.None)[1].Split(new char[] { ',' })[0].Split(new char[] { '"' })[3].Replace("\"", "").Trim();
                }
                else if (type == ResultType.Scan)
                {
                    String link = "http://www.virustotal.com/file-scan/report.html?id=";
                    string id = json.Split(new char[] { ',' })[0].Split(new char[] { ':' })[1].Replace("\"", "").Trim();
                    return String.Format("{0}{1}",link,id);
                }
                else
                {
                    throw new NotImplementedException("Result type is unknown!");
                }
            }
            catch
            {
                throw;
            }
        }

        #region Report Parser
        private DateTime ParseReportDate(String json)
        {
            try
            {
                string date = json.Split(new char[] { '{' })[1].Split(new char[] { '"' })[3];
                return DateTime.Parse(date);
            }
            catch
            {
                throw;
            }
        }

        private Dictionary<String, String> ParseAntiVirus(String json)
        {
            try
            {
                Dictionary<String, String> dav = new Dictionary<string, string>();
                string[] av = json.Split(new char[] { '{' })[2].Split(new char[] { '}' })[0].Split(new char[] {','});

                foreach (string s in av)
                {
                    //"nProtect": ""

                    String key = s.Split(new char[] {':'})[0].Replace("\"","").Trim();
                    String value = s.Split(new char[] { ':' })[1].Replace("\"", "").Trim(); ;
                    dav.Add(key, value);
                }

                return dav;
            }
            catch
            {
                throw;
            }
        }

        private int ParseMalwareCount(Dictionary<String, String> DictionaryAV)
        {
            try
            {
                int match = 0;
                foreach (KeyValuePair<string, string> kvp in DictionaryAV)
                {
                    if (!String.IsNullOrEmpty(kvp.Value))
                    {
                        match++;
                    }
                }

                return match;
            }
            catch
            {
                throw;
            }
        }
  
        private int ParseMalwarePercent(long complete, long total)
        {
            try
            {
                return Convert.ToInt32(complete * 100 / total);
            }
            catch
            {
                throw;
            }
        }

        private Boolean ParseMalwareFound(int count)
        {
            if (count > 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        #endregion

    }
}
